"""
物品 Request VO
"""

from pydantic import model_validator

import utils.enum_utils as enum
from models import (
    ListRequestBase,
    QueryFieldBase,
    RequestBase,
)
from models.other import Dimensions
from my_typing import *
from utils.data_utils.special import ObjectIdStr
from utils.validator_utils.pydantic_validator.field import (
    BodyCharField,
    BodyDecimalField,
    BodyIntegerField,
    BodyListField,
    BodyNormalField,
    PathCharField,
    QueryCharField,
)


class FamilyItemPathField:
    """ 物品 | 路径 | 字段 """

    item_id: ObjectIdStr = PathCharField(..., title="物品 ID")


class FamilyItemDetailRequest(RequestBase):
    """ 物品 | 详情 | 请求 """

    item_id: ObjectIdStr = FamilyItemPathField.item_id


class FamilyItemCreateRequest(RequestBase):
    """ 物品 | 创建 | 请求 """

    alias: StrOrNone = BodyCharField(None, title="别名", min_length=3, max_length=32)
    brand: StrOrNone = BodyCharField(None, title="品牌", max_length=32)
    category: enum.ItemCategory | None = BodyCharField(None, title="物品类别")
    colors: list[enum.Color] = BodyListField(default_factory=list, title="颜色列表")
    description: StrOrNone = BodyCharField(None, title="描述", min_length=1, max_length=200)
    dimensions: Dimensions | None = BodyNormalField(..., description="物品的尺寸（长宽高）")
    expire_date: DateOrNone = BodyNormalField(None, title="过期日期")
    extra_info: DictOrNone = BodyNormalField(default_factory=dict, title="额外信息")
    images: list[ObjectIdStr] = BodyListField(default_factory=list, title="图片列表")
    main_image: ObjectIdStr | None = BodyCharField(None, title="主图")
    name: str = BodyCharField(..., title="名称", min_length=1, max_length=32)
    purchase_date: DateOrNone = BodyNormalField(None, title="购买日期")
    position_id: ObjectIdStr = BodyCharField(..., title="位置 ID")
    price: FloatOrNone = BodyDecimalField(None, title="价格", min_value=0, max_value=99999)
    size: enum.Size | None = BodyCharField(None, title="尺寸")
    status: enum.ItemStatus = BodyCharField(None, title="状态")
    tags: ListStr = BodyListField(default_factory=list, title="标签列表")
    valid_days: IntOrNone = BodyIntegerField(None, title="有效期（天）", min_value=0, max_value=9999)

    @model_validator(mode="before")
    def calc_date_related_data(self) -> Self:
        """
        计算日期相关的数据

            - 购买日期
            - 有效期（天）
            - 过期日期
        """

        purchase_date: DateOrNone = self.purchase_date  # noqa: ignore[attribute]
        valid_days: IntOrNone = self.valid_days  # noqa: ignore[attribute]
        expire_date: DateOrNone = self.expire_date  # noqa: ignore[attribute]

        # 数据都有，判断是否合法
        if (
            purchase_date is not None
            and valid_days is not None
            and expire_date is not None
            and expire_date != purchase_date + timedelta(days=valid_days)
        ):
            raise ValueError("购买日期、有效期（天）和过期日期不合法")

        # 有购买日期
        if purchase_date is not None:
            # 有效期（天）不为空 & 过期日期为空
            if (
                valid_days is not None
                and expire_date is None
            ):
                self.expire_date = purchase_date + timedelta(days=valid_days)

            #  过期日期不为空 & 有效期（天）为空
            if (
                expire_date is not None
                and valid_days is None
            ):
                self.valid_days = (expire_date - purchase_date).days

        if (
            purchase_date is None
            and valid_days is not None
            and expire_date is not None
        ):
            self.purchase_date = expire_date - timedelta(days=valid_days)

        return self

    # @root_validator
    # def calc_date_related_data(cls, values: dict) -> dict:
    #     """
    #     计算日期相关的数据
    #
    #         - 购买日期
    #         - 有效期（天）
    #         - 过期日期
    #     """
    #
    #     purchase_date: DateOrNone = values.get("purchase_date")
    #     valid_days: IntOrNone = values.get("valid_days")
    #     expire_date: DateOrNone = values.get("expire_date")
    #
    #     # 数据都有，判断是否合法
    #     if (
    #         purchase_date is not None
    #         and valid_days is not None
    #         and expire_date is not None
    #         and expire_date != purchase_date + timedelta(days=valid_days)
    #     ):
    #         raise ValueError("购买日期、有效期（天）和过期日期不合法")
    #
    #     # 有购买日期
    #     if purchase_date is not None:
    #         # 有效期（天）不为空 & 过期日期为空
    #         if (
    #             valid_days is not None
    #             and expire_date is None
    #         ):
    #             values["expire_date"] = purchase_date + timedelta(days=valid_days)
    #
    #         #  过期日期不为空 & 有效期（天）为空
    #         if (
    #             expire_date is not None
    #             and valid_days is None
    #         ):
    #             values["valid_days"] = (expire_date - purchase_date).days
    #
    #     if (
    #         purchase_date is None
    #         and valid_days is not None
    #         and expire_date is not None
    #     ):
    #         values["purchase_date"] = expire_date - timedelta(days=valid_days)
    #
    #     return values


class FamilyItemUpdateRequest(FamilyItemCreateRequest):
    """ 物品 | 更新 | 请求 """

    item_id: ObjectIdStr | None = PathCharField(..., title="物品 ID")


class FamilyItemListRequest(ListRequestBase):
    """ 物品 | 列表 | 请求 """

    # -------------------- 排序字段 --------------------
    sort_by_brand: enum.MongoSortOrNone = QueryCharField(None, title="根据品牌排序")
    sort_by_category: enum.MongoSortOrNone = QueryCharField(None, title="根据物品类别排序")
    sort_by_color: enum.MongoSortOrNone = QueryCharField(None, title="根据颜色排序")
    sort_by_create_time: enum.MongoSortOrNone = QueryCharField(None, title="根据创建时间排序")
    sort_by_expire_date: enum.MongoSortOrNone = QueryCharField(None, title="根据过期日期排序")
    sort_by_name: enum.MongoSortOrNone = QueryCharField(None, title="根据名称日期排序")
    sort_by_purchase_date: enum.MongoSortOrNone = QueryCharField(None, title="根据购买日期排序")
    sort_by_position_id: enum.MongoSortOrNone = QueryCharField(None, title="根据位置 ID 排序")
    sort_by_price: enum.MongoSortOrNone = QueryCharField(None, title="根据价格排序")
    sort_by_size: enum.MongoSortOrNone = QueryCharField(None, title="根据尺寸排序")
    sort_by_status: enum.MongoSortOrNone = QueryCharField(None, title="根据状态排序")
    sort_by_update_time: enum.MongoSortOrNone = QueryCharField(None, title="根据更新时间排序")
    sort_by_valid_days: enum.MongoSortOrNone = QueryCharField(None, title="根据有效期（天）排序")

    # -------------------- 查询字段 --------------------
    alias: StrOrNone = QueryCharField(None, title="根据别名模糊查询")
    brand: StrOrNone = QueryCharField(None, title="根据品牌模糊查询")
    category: enum.ItemCategory | None = QueryCharField(None, title="根据物品类别查询")
    color: enum.Color | None = QueryCharField(None, title="根据颜色查询")
    description: StrOrNone = QueryCharField(None, title="根据描述模糊查询")
    name: StrOrNone = QueryCharField(None, title="根据名称模糊查询")
    position_id: ObjectIdStr | None = QueryCharField(..., title="根据位置 ID 查询")
    size: enum.Size | None = QueryCharField(None, title="根据尺寸查询")
    status: enum.ItemStatus | None = QueryCharField(None, title="根据状态查询")

    @classmethod
    def from_query(
        cls,
        page: int = QueryFieldBase.page,
        page_size: int = QueryFieldBase.page_size,
        sort_by_brand: enum.MongoSortOrNone = QueryCharField(None, title="根据品牌排序"),
        sort_by_category: enum.MongoSortOrNone = QueryCharField(None, title="根据物品类别排序"),
        sort_by_create_time: enum.MongoSortOrNone = QueryCharField(None, title="根据创建时间排序"),
        sort_by_color: enum.MongoSortOrNone = QueryCharField(None, title="根据颜色排序"),
        sort_by_expire_date: enum.MongoSortOrNone = QueryCharField(None, title="根据过期日期排序"),
        sort_by_name: enum.MongoSortOrNone = QueryCharField(None, title="根据名称日期排序"),
        sort_by_purchase_date: enum.MongoSortOrNone = QueryCharField(None, title="根据购买日期排序"),
        sort_by_position_id: enum.MongoSortOrNone = QueryCharField(None, title="根据位置 ID 排序"),
        sort_by_price: enum.MongoSortOrNone = QueryCharField(None, title="根据价格排序"),
        sort_by_size: enum.MongoSortOrNone = QueryCharField(None, title="根据尺寸排序"),
        sort_by_status: enum.MongoSortOrNone = QueryCharField(None, title="根据状态排序"),
        sort_by_update_time: enum.MongoSortOrNone = QueryCharField(None, title="根据更新时间排序"),
        sort_by_valid_days: enum.MongoSortOrNone = QueryCharField(None, title="根据有效期（天）排序"),
        alias: StrOrNone = QueryCharField(None, title="根据别名模糊查询"),
        brand: StrOrNone = QueryCharField(None, title="根据品牌模糊查询"),
        category: enum.ItemCategory | None = QueryCharField(None, title="根据物品类别查询"),
        color: enum.Color | None = QueryCharField(None, title="根据颜色查询"),
        description: StrOrNone = QueryCharField(None, title="根据描述模糊查询"),
        name: StrOrNone = QueryCharField(None, title="根据名称模糊查询"),
        position_id: ObjectIdStr | None = QueryCharField(..., title="根据位置 ID 查询"),
        size: enum.Size | None = QueryCharField(None, title="根据尺寸查询"),
        status: enum.ItemStatus | None = QueryCharField(None, title="根据状态查询"),
    ) -> "FamilyItemListRequest":
        return cls(
            page=page,
            page_size=page_size,
            sort_by_brand=sort_by_brand,
            sort_by_category=sort_by_category,
            sort_by_color=sort_by_color,
            sort_by_create_time=sort_by_create_time,
            sort_by_expire_date=sort_by_expire_date,
            sort_by_name=sort_by_name,
            sort_by_purchase_date=sort_by_purchase_date,
            sort_by_position_id=sort_by_position_id,
            sort_by_price=sort_by_price,
            sort_by_size=sort_by_size,
            sort_by_status=sort_by_status,
            sort_by_update_time=sort_by_update_time,
            sort_by_valid_days=sort_by_valid_days,
            alias=alias,
            brand=brand,
            category=category,
            color=color,
            description=description,
            name=name,
            position_id=position_id,
            size=size,
            status=status,
        )
